using GrapeCity.Forguncy.Commands;
using GrapeCity.Forguncy.Plugin;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.CompilerServices.RuntimeHelpers;

namespace GetCSVData
{
    [Icon("pack://application:,,,/GetCSVData;component/Resources/CSV16.png")]
    [Designer("GetCSVData.Designer.GetCSVDataServerCommandDesigner, GetCSVData")]
    [Category("CSV数据处理")]
    [Description("获取的CSV数据将会是一个二维数组（Array）")]
    public class GetCSVDataServerCommand : Command, ICommandExecutableInServerSideAsync
    {
        [Description("通过标题将CSV数据转成对象（Key-Value）数组")]
        [DisplayName("是否存在标题")]
        [Browsable(false)]
        public bool IsExistedTitle { get; set; } = false;

        [Description("CSV文件编码")]
        [DisplayName("CSV文件编码")]
        public CsvEncoding CsvEncoding { get; set; } = CsvEncoding.UTF8;

        [Description("CSV数据分隔符，默认逗号")]
        [DisplayName("CSV数据分隔符")]
        public CsvDataSeparator CsvDataDelimiter { get; set; } = CsvDataSeparator.COMMA;

        [Description("文件全路径，需要附带CSV后缀。多个文件，英文分号分割。")]
        [DisplayName("CSV文件路径")]
        [FormulaProperty]
        [Required]
        public object CSVFile { get; set; }

        [Description("获取指定CSV文件中指定范围中的数据")]
        [DisplayName("是否获取指定行列数据")]
        public bool IsSubarray { get; set; } = false;

        [Description("数据行开始标识")]
        [DisplayName("数据行开始标识")]
        [FormulaProperty]
        public object RowStartFlag { get; set; }


        [Description("数据行结束标识")]
        [DisplayName("数据行结束标识")]
        [FormulaProperty]
        public object RowEndFlag { get; set; }

        [Description("指定行列的开始行，从1开始")]
        [DisplayName("数据开始行")]
        [FormulaProperty]
        [Required]
        public object RowStart { get; set; } = 1;

        [DisplayName("数据结束行")]
        [FormulaProperty]
        public object RowEnd { get; set; }

        [Description("指定行列的开始行，从1开始")]
        [DisplayName("数据开始列")]
        [FormulaProperty]
        [Required]
        public object ColumnStart { get; set; } = 1;

        [DisplayName("数据结束列")]
        [FormulaProperty]
        public object ColumnEnd { get; set; }

        [ResultToProperty]
        [DisplayName("CSV数据")]
        public string ResultToCSVData { get; set; } = "CSVData";

        [Description("如果是多个文件，文件内容返回到这个变量。兼容之前版本功能。")]
        [ResultToProperty]
        [DisplayName("CSV数据(多文件)")]
        public string ResultToCSVDataMultiple { get; set; } = "CSVDataMultiple";

        [ResultToProperty]
        [DisplayName("返回码")]
        [Description("")]
        public string ErrCode { get; set; } = "返回码";

        [ResultToProperty]
        [DisplayName("返回信息")]
        [Description("")]
        public string Message { get; set; } = "返回信息";


        public async Task<ExecuteResult> ExecuteAsync(IServerCommandExecuteContext dataContext)
        {
            // 获取文件路径
            var csvFilePath = await dataContext.EvaluateFormulaAsync(CSVFile);
            var encoding = await dataContext.EvaluateFormulaAsync(CsvEncoding);
            var csvEncoding = GetEncoding((CsvEncoding)encoding);
            var separator = GetDataSeparator();

            try
            {
                // 处理多个文件（用分号分割）
                var filePaths = csvFilePath.ToString().Split(';', StringSplitOptions.RemoveEmptyEntries);

                if (filePaths.Length == 0)
                {
                    string message = "错误：未找到有效的CSV文件路径";
                    dataContext.Parameters[ErrCode] = -1;
                    dataContext.Parameters[Message] = message;
                    return new ExecuteResult() { ErrCode = -1, Message = message };
                }

                // 验证所有文件路径
                var invalidFiles = new List<string>();
                foreach (var filePath in filePaths)
                {
                    if (!File.Exists(filePath.Trim()))
                    {
                        invalidFiles.Add(filePath.Trim());
                    }
                }

                if (invalidFiles.Any())
                {
                    string message = $"错误：以下文件不存在：\r\n{string.Join("\r\n", invalidFiles)}"; 
                    dataContext.Parameters[ErrCode] = -1;
                    dataContext.Parameters[Message] = message;
                    return new ExecuteResult() { ErrCode = -1, Message = message };
                }

                // 单个文件：返回 List<string[]>
                if (filePaths.Length == 1)
                {
                    var fileData = await ProcessSingleFileAsync(dataContext, filePaths[0].Trim(), csvEncoding, separator);
                    dataContext.Parameters[ResultToCSVData] = fileData?.ToArray();
                }
                // 多个文件：返回 Dictionary<string, List<string[]>>
                else
                {
                    var csvRecordsMultiple = new Dictionary<string, List<string[]>>();

                    foreach (var filePath in filePaths)
                    {
                        var trimmedFilePath = filePath.Trim();
                        var fileData = await ProcessSingleFileAsync(dataContext, trimmedFilePath, csvEncoding, separator);

                        if (fileData != null)
                        {
                            csvRecordsMultiple[trimmedFilePath] = fileData;
                        }
                    }

                    dataContext.Parameters[ResultToCSVDataMultiple] = csvRecordsMultiple;
                }
            }
            catch (Exception ex)
            {
                dataContext.Parameters[ErrCode] = -1;
                dataContext.Parameters[Message] = ex.ToString();
                return new ExecuteResult() { ErrCode = -1, Message = ex.ToString() };

            }
            return new ExecuteResult();
        }

        /// <summary>
        /// 处理单个CSV文件
        /// </summary>
        /// <param name="dataContext">命令执行上下文</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="encoding">文件编码</param>
        /// <param name="separator">分隔符</param>
        /// <returns>文件数据</returns>
        private async Task<List<string[]>> ProcessSingleFileAsync(IServerCommandExecuteContext dataContext, string filePath, Encoding encoding, char[] separator)
        {
            var csvRecords = new List<string[]>();

            // 子数据的结点
            int rowStart, rowEnd, columnStart, columnEnd;
            string rowStartFlag, rowEndFlag;

            try
            {
                // 读取文件指定部分数据
                if (IsSubarray)
                {
                    rowStart = Convert.ToInt32(await dataContext.EvaluateFormulaAsync(RowStart));
                    rowEnd = Convert.ToInt32(await dataContext.EvaluateFormulaAsync(RowEnd));
                    columnStart = Convert.ToInt32(await dataContext.EvaluateFormulaAsync(ColumnStart));
                    columnEnd = Convert.ToInt32(await dataContext.EvaluateFormulaAsync(ColumnEnd));
                    rowStartFlag = (await dataContext.EvaluateFormulaAsync(RowStartFlag))?.ToString();
                    rowEndFlag = (await dataContext.EvaluateFormulaAsync(RowEndFlag))?.ToString();

                    if (string.IsNullOrEmpty(rowEndFlag))
                    {
                        rowEndFlag = rowStartFlag;
                    }

                    if (!CheckData(rowStart, rowEnd, columnStart, columnEnd))
                    {
                        // 如果数据验证失败，记录错误但不中断处理其他文件
                        csvRecords.Add(new string[] { $"文件 {filePath} 数据验证失败：输入开始结束行列不正确" });
                        return csvRecords;
                    }

                    using (var reader = new StreamReader(filePath, encoding))
                    {
                        // 行标识符优先处理
                        if (string.IsNullOrEmpty(rowStartFlag))
                        {
                            var index = 1;
                            while (await reader.ReadLineAsync() is { } str)
                            {
                                // 设置了结束行，处理到结束行时返回，或者处理到结束标识符号返回
                                if ((rowEnd != 0 && index > rowEnd) || str == rowEndFlag)
                                {
                                    break;
                                }
                                // --- 添加这行：过滤空行 ---
                                if (string.IsNullOrWhiteSpace(str))
                                {
                                    index++;
                                    continue; // 跳过当前空行，但要记得增加行号
                                }
                                // -----------------------
                                if (index >= rowStart)
                                {
                                    var array = DealLineData(str, separator, columnStart, columnEnd);
                                    csvRecords.Add(array);
                                }
                                index++;
                            }
                        }
                        // 处理行起始标识符
                        else
                        {
                            var start = false;
                            while (await reader.ReadLineAsync() is { } str)
                            {
                                // 遇到空白行或者到结束标识行停止
                                //if ((start && str == rowEndFlag) || string.IsNullOrWhiteSpace(str))
                                if ((start && str == rowEndFlag))//遇到空白行 不停止
                                {
                                    break;
                                }
                                // --- 添加这行：过滤空行 ---
                                if (string.IsNullOrWhiteSpace(str))
                                {
                                    continue; // 跳过当前空行
                                }
                                // -----------------------
                                if (start)
                                {
                                    var array = DealLineData(str, separator, columnStart, columnEnd);
                                    csvRecords.Add(array);
                                }
                                if (str == rowStartFlag)
                                {
                                    start = true;
                                }
                            }
                        }
                    }
                }
                // 读取文件所有数据
                else
                {
                    using var reader = new StreamReader(filePath, encoding);
                    while (await reader.ReadLineAsync() is { } str)
                    {
                        // --- 添加这行：过滤空行 ---
                        if (string.IsNullOrWhiteSpace(str)) continue;
                        // -----------------------
                        var array = str.Split(separator);
                        csvRecords.Add(array);
                    }
                }
            }
            catch (Exception ex)
            {
                // 如果单个文件处理失败，记录错误信息但不中断其他文件
                csvRecords.Add(new string[] { $"文件 {filePath} 处理失败：{ex.Message}" });
            }

            return csvRecords;
        }

        private static string[] DealLineData(string lineData, char[] separator, int columnStart, int columnEnd)
        {
            var array = lineData.Split(separator);
            if (columnEnd == 0)
            {
                array = array.Skip(columnStart - 1).ToArray();
            }
            else if (columnEnd < array.Length)
            {
                array = array.Skip(columnStart - 1).Take(columnEnd - columnStart + 1).ToArray();
            }

            return array;
        }

        private static bool CheckData(int rowS, int rowE, int colS, int colE)
        {
            bool rowResult = false;
            bool colResult = false;

            if (rowE == 0 && rowS >= 1 || rowS >= 1 && rowE >= rowS)
            {
                rowResult = true;
            }

            if (colE == 0 && colS >= 1 || colS >= 1 && colE >= colS)
            {
                colResult = true;
            }

            return rowResult && colResult;
        }

        private static Encoding GetEncoding(CsvEncoding csvEncoding)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            var encoding = csvEncoding switch
            {
                CsvEncoding.GB2312 => Encoding.GetEncoding("GB2312"),
                _ => Encoding.UTF8
            };

            return encoding;
        }

        private char[] GetDataSeparator()
        {
            return CsvDataDelimiter switch
            {
                CsvDataSeparator.COMMA => ",".ToCharArray(),
                CsvDataSeparator.SPACE => " ".ToCharArray(),
                CsvDataSeparator.TAB => "\t".ToCharArray(),
                CsvDataSeparator.SAPCE_OR_TAB => new char[] { ' ', '\t' },
                _ => ",".ToCharArray()
            };
        }

        public override bool GetDesignerPropertyVisible(string propertyName, CommandScope commandScope)
        {
            if (propertyName == nameof(RowStart) || propertyName == nameof(RowEnd) ||
                propertyName == nameof(ColumnStart) || propertyName == nameof(ColumnEnd) ||
                propertyName == nameof(RowStartFlag) || propertyName == nameof(RowEndFlag))
            {
                return IsSubarray;
            }

            return true;
        }

        public override string ToString()
        {
            return "获取CSV数据";
        }

        public override CommandScope GetCommandScope()
        {
            return CommandScope.ExecutableInServer;
        }
    }

    public enum CsvEncoding
    {
        [Description("UTF-8")] UTF8,
        [Description("GB2312")] GB2312

    }

    public enum CsvDataSeparator
    {
        [Description("逗号")] COMMA,
        [Description("空格")] SPACE,
        [Description("制表符")] TAB,
        [Description("空格或制表符")] SAPCE_OR_TAB,
    }
}